// （联合）性能测试
// 主要测试要素：同步和异步的单线程和多线程

#include "../logsystem/snowdragon.h"
#include <chrono>

void SummativeTest(const std::string& logger_name, size_t thread_count, size_t message_count, size_t per_message_len)
{
    snowdragon::Logger::ptr logger = snowdragon::getLogger(logger_name);
    if(logger.get() == nullptr)
    {
        FATAL_LOG_DEFAULT("SummativeTest, %s logger is not exists", logger_name.c_str());
        return;
    }
    // 存储创建的线程，方便在最后进行join等待
    std::vector<std::thread> threads;               // 不要加(thread_count)，否则在等待是会报参数错误
    std::vector<double> cost_time(thread_count);            // 存储各线程进行日志输出时所消耗的时间
    std::string message(per_message_len, '1');              // 构建日志主体（有效载荷）数据
    size_t per_thread_make_message = message_count / thread_count;      // 每个线程需要处理的消息数
    // std::cout << "SummativeTest thread start before" << std::endl;
    std::cout << "处理日志线程数量: " << thread_count << std::endl;
    std::cout << "处理日志总数量: " << message_count << std::endl;
    std::cout << "处理日志总大小: " << (message_count * per_message_len * 1.0) / (1024 * 1024) << "MB" << std::endl;
    for(int i = 0; i < thread_count; ++i)           // 各线程执行开始
    {
        threads.emplace_back([&, i]{
                auto start = std::chrono::high_resolution_clock::now();
                for(int j = 0; j < per_thread_make_message; ++j)
                    logger->fatal("%s", message.c_str());
                auto end = std::chrono::high_resolution_clock::now();
                auto cost = std::chrono::duration_cast<std::chrono::duration<double>>(end - start);     // 计算消耗时间
                cost_time[i] = cost.count();
                std::cout << " \t线程" << i << ", 处理日志: " << per_thread_make_message << "条， 耗时：" << cost_time[i] << "s\n";
            });
    }
    // std::cout << "SummativeTest thread start after" << std::endl;
    for(auto& thread : threads)     // 等待线程
        thread.join();
    // 总消耗时间，即消耗时间的最大值
    double max_cost = cost_time[0];     // 用double类型，不然小数部分会被丢掉
    // for(int i = 1; i < thread_count; ++i)
    //     max_cost = max_cost < costs[i] ? costs[i] : max_cost;
    for(auto cost : cost_time)
        max_cost = max_cost < cost ? cost : max_cost;

    std::cout << "日志执行结束,总耗时: " << max_cost << "s" << std::endl;
    std::cout << "平均每秒处理 " << (message_count / max_cost) << " 条日志" << std::endl; 
    std::cout << "每秒处理日志大小: " << (message_count * per_message_len) / max_cost / (1024 * 1024) << "MB" << std::endl;
}

void SyncLoggerTest(size_t thread_count, size_t message_count, size_t per_message_len)
{
    static size_t num = 0;
    std::shared_ptr<snowdragon::GlobalLoggerBuilder> glb(new snowdragon::GlobalLoggerBuilder);
    std::string logger_name = "SyncLogger" + std::to_string(num++);     // 保存下来，传参方便
    glb->buildLoggerName(logger_name);
    glb->buildLoggerType(snowdragon::Logger::LoggerType::SYNC_LOGGER);
    glb->buildLoggerSink<snowdragon::specificFileSink>("./logfiles/SyncLogger_test.log");
    snowdragon::Logger::ptr logger = glb->build();
    // snowdragon::LoggerManager::getInstance().pushLogger(logger);            // 全局建造者，自动加入，无需
    printf("************SyncLoggerTest日志器 %s 测试开始*************\n", logger->getLoggerName().c_str());
    SummativeTest(logger_name, thread_count, message_count, per_message_len);
    printf("************SyncLoggerTest日志器 %s 测试结束*************\n", logger->getLoggerName().c_str());
}

void AsyncLoggerTest(size_t thread_count, size_t message_count, size_t per_message_len)
{
    static size_t num = 0;
    std::shared_ptr<snowdragon::GlobalLoggerBuilder> glb(new snowdragon::GlobalLoggerBuilder);
    std::string logger_name = "AsyncLogger" + std::to_string(num++);
    glb->buildLoggerName(logger_name);
    glb->buildLoggerType(snowdragon::Logger::LoggerType::ASYNC_LOGGER);
    glb->buildLoggerSink<snowdragon::specificFileSink>("./logfiles/AsyncLogger_test.log");
    snowdragon::Logger::ptr logger = glb->build();
    
    // 以下是对日志器的弹出和压入测试，可不必加入

    // snowdragon::LoggerManager::getInstance().popLogger(logger_name);
    // snowdragon::LoggerManager::getInstance().pushLogger(logger);

    // logger->modifyAsyncLoggerAndLooperSafeType(snowdragon::AsyncLooperSafeType::UNSAFE_ASYNC_LOOPER);

    // snowdragon::LoggerManager::getInstance().pushLogger(logger);     // 全局build时已经自动加入了，无需手动设置
    printf("************AsyncLoggerTest日志器 %s 测试开始*************\n", logger->getLoggerName().c_str());
    SummativeTest(logger_name, thread_count, message_count, per_message_len);
    printf("************AsyncLoggerTest日志器 %s 测试结束*************\n", logger->getLoggerName().c_str());
}

int main()
{
    // SyncLoggerTest(1, 2000000, 100);
    // SyncLoggerTest(4, 2000000, 100);

    // AsyncLoggerTest(1, 2000000, 100);
    AsyncLoggerTest(4, 2000000, 100);

    return 0;
}